using Firestarter.DB.Schema.BO;
using Firestarter.DB.Schema.Logic;
using Firestarter.DB.Schema.Test.Logic;
using Firestarter.DB.Schema.UI;
using FireStarterModeller.BO;
using FireStarterModeller.Test;
using NUnit.Framework;
using Rhino.Mocks;

namespace Firestarter.DB.Schema.Test.UI
{
    [TestFixture]
    public class TestApproveSchemaChangesWizardStep : TestBase
    {
        [Test]
        public void Test_ReverseEngineering()
        {
            //---------------Set up test pack-------------------
            ApproveSchemaChangesWizardStep wizardStep = new ApproveSchemaChangesWizardStep();
            ReverseEngineering reverseEngineering = new ReverseEngineering
                                                        {
                                                            StoredDatabase = new DBDatabase()
                                                        };
            //-------------Assert Preconditions -------------

            //---------------Execute Test ----------------------
            wizardStep.ReverseEngineering = reverseEngineering;
            //---------------Test Result -----------------------
            Assert.AreSame(reverseEngineering, wizardStep.ReverseEngineering);
            Assert.IsNotNull(wizardStep.SchemaMerger);
            Assert.AreSame(reverseEngineering, wizardStep.SchemaMerger.ReverseEngineering);
            Assert.IsNull(wizardStep.DatabaseInfoChangesControl.Database);
            //Assert.AreSame(reverseEngineering.StoredDatabase, wizardStep.StoredDatabase);
            //Assert.AreSame(reverseEngineering.StoredDatabase, wizardStep.DatabaseInfoChangesControl.Database);
        }

        [Test]
        public void Test_ReverseEngineering_SetToNull()
        {
            //---------------Set up test pack-------------------
            ApproveSchemaChangesWizardStep wizardStep = new ApproveSchemaChangesWizardStep();
            wizardStep.ReverseEngineering = new ReverseEngineering {StoredDatabase = new DBDatabase()};
            //-------------Assert Preconditions -------------
            Assert.IsNotNull(wizardStep.ReverseEngineering);
            Assert.IsNotNull(wizardStep.SchemaMerger);
            Assert.IsNull(wizardStep.DatabaseInfoChangesControl.Database);
            //---------------Execute Test ----------------------
            wizardStep.ReverseEngineering = null;
            //---------------Test Result -----------------------
            Assert.IsNull(wizardStep.ReverseEngineering);
            Assert.IsNull(wizardStep.SchemaMerger);
            Assert.IsNull(wizardStep.DatabaseInfoChangesControl.Database);
        }

        [Test]
        public void Test_StoredDatabaseInfo_Changed()
        {
            //---------------Set up test pack-------------------
            ApproveSchemaChangesWizardStep wizardStep = new ApproveSchemaChangesWizardStep();
            ReverseEngineering reverseEngineering = new ReverseEngineering();
            wizardStep.ReverseEngineering = reverseEngineering;
            DBDatabase dbDatabase = new DBDatabase();
            wizardStep.SchemaMerger = new SchemaMergerMockWithDelegate(null);
            wizardStep.InitialiseStep();
            //-------------Assert Preconditions -------------
            Assert.IsNotNull(wizardStep.ReverseEngineering);
            Assert.IsNull(wizardStep.StoredDatabase);
            Assert.IsNull(wizardStep.DatabaseInfoChangesControl.Database);
            //---------------Execute Test ----------------------
            reverseEngineering.StoredDatabase = dbDatabase;
            //---------------Test Result -----------------------
            Assert.AreSame(reverseEngineering, wizardStep.ReverseEngineering);
            Assert.AreSame(dbDatabase, wizardStep.StoredDatabase);
            Assert.AreSame(dbDatabase, wizardStep.DatabaseInfoChangesControl.Database);
        }

        [Test]
        public void Test_StoredDatabaseInfo_Changed_ToNull()
        {
            //---------------Set up test pack-------------------
            ApproveSchemaChangesWizardStep wizardStep = new ApproveSchemaChangesWizardStep();
            ReverseEngineering reverseEngineering = new ReverseEngineering {StoredDatabase = new DBDatabase()};
            wizardStep.ReverseEngineering = reverseEngineering;
            wizardStep.SchemaMerger = new SchemaMergerMockWithDelegate(null);
            wizardStep.InitialiseStep();
            //-------------Assert Preconditions -------------
            Assert.IsNotNull(wizardStep.ReverseEngineering);
            Assert.IsNotNull(wizardStep.StoredDatabase);
            Assert.IsNotNull(wizardStep.DatabaseInfoChangesControl.Database);
            //---------------Execute Test ----------------------
            reverseEngineering.StoredDatabase = null;
            //---------------Test Result -----------------------
            Assert.AreSame(reverseEngineering, wizardStep.ReverseEngineering);
            Assert.IsNotNull(wizardStep.ReverseEngineering);
            Assert.IsNull(wizardStep.StoredDatabase);
            Assert.IsNull(wizardStep.DatabaseInfoChangesControl.Database);
        }

        [Test]
        public void Test_InitialiseStep_RunsSchemaMerger()
        {
            //---------------Set up test pack-------------------
            ApproveSchemaChangesWizardStep wizardStep = new ApproveSchemaChangesWizardStep();
            ReverseEngineering reverseEngineering = new ReverseEngineering {StoredDatabase = new DBDatabase()};
            wizardStep.ReverseEngineering = reverseEngineering;
            bool schemaMergerHasBeenRun = false;
            wizardStep.SchemaMerger = new SchemaMergerMockWithDelegate(delegate { schemaMergerHasBeenRun = true; });
            //-------------Assert Preconditions -------------
            Assert.IsFalse(schemaMergerHasBeenRun);
            //---------------Execute Test ----------------------
            wizardStep.InitialiseStep();
            //---------------Test Result -----------------------
            Assert.IsTrue(schemaMergerHasBeenRun);
        }

        [Test]
        public void Test_InitialiseStep_UpdatesUI()
        {
            //---------------Set up test pack-------------------
            ApproveSchemaChangesWizardStep wizardStep = new ApproveSchemaChangesWizardStep();
            ReverseEngineering reverseEngineering = new ReverseEngineering {StoredDatabase = new DBDatabase()};
            wizardStep.ReverseEngineering = reverseEngineering;
            bool schemaMergerHasBeenRun = false;
            bool databaseChangesControlVisibleDuringMerge = false;
            bool busyLoadingChangesControlVisibleDuringMerge = false;
            wizardStep.SchemaMerger = new SchemaMergerMockWithDelegate(delegate
                                                                           {
                                                                               schemaMergerHasBeenRun = true;
                                                                               busyLoadingChangesControlVisibleDuringMerge
                                                                                   =
                                                                                   wizardStep.LoadingChangesGroupBox.
                                                                                       Visible;
                                                                               databaseChangesControlVisibleDuringMerge
                                                                                   =
                                                                                   wizardStep.DatabaseInfoChangesControl
                                                                                       .Visible;
                                                                           });
            //-------------Assert Preconditions -------------
            Assert.IsFalse(schemaMergerHasBeenRun);
            Assert.IsNull(wizardStep.DatabaseInfoChangesControl.Database);
            //---------------Execute Test ----------------------
            wizardStep.InitialiseStep();
            //---------------Test Result -----------------------
            Assert.IsTrue(schemaMergerHasBeenRun);
            Assert.IsTrue(busyLoadingChangesControlVisibleDuringMerge,
                          "BusyLoadingChangesControl Should have been visible during merge.");
            Assert.IsFalse(databaseChangesControlVisibleDuringMerge,
                           "DatabaseChangesControl Should not have been visible during merge.");
            Assert.IsFalse(wizardStep.LoadingChangesGroupBox.Visible,
                           "BusyLoadingChangesControl Should not be visible after the merge.");
            Assert.IsTrue(wizardStep.DatabaseInfoChangesControl.Visible,
                          "DatabaseChangesControl Should be visible after the merge.");
            Assert.IsNotNull(wizardStep.DatabaseInfoChangesControl.Database);
        }

        public class SchemaMergerMockWithDelegate : SchemaMerger
        {
            private readonly SimpleDelegate _simpleDelegate;

            public delegate void SimpleDelegate();

            public SchemaMergerMockWithDelegate(SimpleDelegate simpleDelegate) : base(null)
            {
                _simpleDelegate = simpleDelegate;
            }

            public override void RunMerge()
            {
                if (_simpleDelegate != null) _simpleDelegate();
            }
        }

        [Test]
        public void Test_CancelStep_ShouldCallCancelEdits()
        {
            //---------------Set up test pack-------------------
            IReverseEngineering reverseEngineering = MockRepository.GenerateMock<IReverseEngineering>();

            IDBDatabase storedDatabase = SetStoredDatabase(reverseEngineering);

            ApproveSchemaChangesWizardStep wizardStep = new ApproveSchemaChangesWizardStep();
            wizardStep.ReverseEngineering = reverseEngineering;

            //-------------Assert Preconditions -------------
            Assert.AreSame(reverseEngineering, wizardStep.ReverseEngineering);
            storedDatabase.AssertWasNotCalled(database => database.CancelEdits());
            //---------------Execute Test ----------------------
            wizardStep.CancelStep();
            //---------------Test Result -----------------------
            storedDatabase.AssertWasCalled(database => database.CancelEdits());
        }

        private static IDBDatabase SetStoredDatabase(IReverseEngineering reverseEngineering)
        {
            var storedDatabase = MockRepository.GenerateMock<IDBDatabase>();
            reverseEngineering.Stub(engineering => engineering.StoredDatabase).Return(storedDatabase);
            return storedDatabase;
        }

        [Test]
        public void Test_CancelStep_WhenNullDBDatabase_ShouldDoNothing()
        {
            //---------------Set up test pack-------------------
            IReverseEngineering reverseEngineering = MockRepository.GenerateMock<IReverseEngineering>();

            ApproveSchemaChangesWizardStep wizardStep = new ApproveSchemaChangesWizardStep();
            wizardStep.ReverseEngineering = reverseEngineering;
            //-------------Assert Preconditions -------------
            Assert.AreSame(reverseEngineering, wizardStep.ReverseEngineering);
            Assert.IsNull(reverseEngineering.StoredDatabase);
            //---------------Execute Test ----------------------
            wizardStep.CancelStep();
            //---------------Test Result -----------------------
            Assert.IsTrue(true, "If it executed method then all is OK");
        }

        [Test]
        public void Test_CancelStep_WhenNullRevEng_ShouldDoNothing()
        {
            //---------------Set up test pack-------------------
            ApproveSchemaChangesWizardStep wizardStep = new ApproveSchemaChangesWizardStep();
            wizardStep.ReverseEngineering = null;
            //-------------Assert Preconditions -------------
            Assert.IsNull(wizardStep.ReverseEngineering);
            Assert.IsNull(wizardStep.StoredDatabase);
            //---------------Execute Test ----------------------
            wizardStep.CancelStep();
            //---------------Test Result -----------------------
            Assert.IsTrue(true, "If it executed method then all is OK");
        }
    }
}